using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace OrbitOne.CRMUpdater.CRM
{
    static public class Extensions
    {
        #region Public Extension Methods
        public static string ToCsv(this DataTable table, char dataDelimiter, char fieldDelimiter)
        {
            var sb = new StringBuilder();
            sb.AppendLine(string.Join(fieldDelimiter.ToString(), table.Columns.Cast<DataColumn>().Select(d => d.Caption.Contains(fieldDelimiter) ? dataDelimiter + d.Caption + dataDelimiter : d.Caption).ToArray()));
            sb.Append(string.Join("\r\n", table.Rows
                                            .Cast<DataRow>()
                                            .Select(row => string.Join(fieldDelimiter.ToString(),
                                                                   row.ItemArray
                                                                              .Select(s => (s.GetType() == typeof(DBNull) ? "" : s.ToString()).Contains(fieldDelimiter) || (s.GetType() == typeof(DBNull) ? "" : s.ToString()).Contains("\n") ? dataDelimiter + (s.GetType() == typeof(DBNull) ? "" : s.ToString()) + dataDelimiter : (s.GetType() == typeof(DBNull) ? "" : s.ToString())).ToArray())).ToArray()));
            return sb.ToString();
        }
        public static DataTable FromCsv(this string csv, char dataDelimiter, char fieldDelimiter)
        {
            var lines = csv.Replace("\r\n", "\n").Split('\n');
            var dt = new DataTable();
            dt.Columns.AddRange(lines.First().splitter(dataDelimiter, fieldDelimiter).Select(c => new DataColumn(c)).ToArray());
            lines.Skip(1).Select(r => { dt.Rows.Add(r.splitter(dataDelimiter, fieldDelimiter).ToArray()); return r; }).ToArray();
            return dt;
        }
        #endregion

        #region Private Extension Methods
        private static IEnumerable<string> splitter(this string row, char dataDelimiter, char fieldDelimiter)
        {
            var ca = row.ToCharArray();
            var ignore = false;
            var start = 0;
            for (var i = 0; i < ca.Length; i++)
            {
                if (ca[i] == dataDelimiter)
                    ignore = !ignore;
                else if (ca[i] == fieldDelimiter && !ignore)
                {
                    yield return row.Substring(start, i - start).Replace(dataDelimiter.ToString(), "");
                    start = i + 1;
                }
            }
            yield return row.Substring(start, ca.Length - start).Replace(dataDelimiter.ToString(), "").Replace("\n", "");
        }
        #endregion
    }
}